{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "ename": "ModuleNotFoundError",
     "evalue": "No module named 'utils'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-1-0ed173f52f87>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnn\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mnn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moverlaps_cuda\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrbbox_overlaps\u001b[0m  \u001b[0;32mimport\u001b[0m \u001b[0mrbbx_overlaps\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moverlaps\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrbox_overlaps\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mrbox_overlaps\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'utils'"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "from utils.overlaps_cuda.rbbox_overlaps  import rbbx_overlaps\n",
    "from utils.overlaps.rbox_overlaps import rbox_overlaps\n",
    "from utils.overlaps_cuda.rbbox_overlaps  import rbbx_overlaps\n",
    "\n",
    "\n",
    "def xyxy2xywh_a(query_boxes):\n",
    "    out_boxes = query_boxes.copy()\n",
    "    out_boxes[:, 0] = (query_boxes[:, 0] + query_boxes[:, 2]) * 0.5\n",
    "    out_boxes[:, 1] = (query_boxes[:, 1] + query_boxes[:, 3]) * 0.5\n",
    "    out_boxes[:, 2] = query_boxes[:, 2] - query_boxes[:, 0]\n",
    "    out_boxes[:, 3] = query_boxes[:, 3] - query_boxes[:, 1]\n",
    "    return out_boxes\n",
    "def generate_anchors(base_size, ratios, scales, rotations):\n",
    "    \"\"\"\n",
    "    Generate anchor (reference) windows by enumerating aspect ratios X\n",
    "    scales w.r.t. a reference window.\n",
    "    \"\"\"\n",
    "    #保持面积不变的情况下调整长宽比\n",
    "\n",
    "    num_anchors = len(ratios) * len(scales) * len(rotations)#anchor的个数，长宽比，scale和旋转角度\n",
    "    # initialize output anchors\n",
    "    anchors = np.zeros((num_anchors, 5))#anchor的5个参数，\n",
    "    # scale base_size\n",
    "    anchors[:, 2:4] = base_size * np.tile(scales, (2, len(ratios) * len(rotations))).T#np.tile（a,(2)）函数的作用就是将函数沿着X轴扩大两倍。如果扩大倍数只有一个，默认为X轴\n",
    "#     print(anchors[:, 2:4])\n",
    "    # compute areas of anchors\n",
    "    areas = anchors[:, 2] * anchors[:, 3]#计算anchor的面积\n",
    "#     print(\"areas\",areas)\n",
    "    # correct for ratios\n",
    "    anchors[:, 2] = np.sqrt(areas / np.repeat(ratios, len(scales) * len(rotations)))\n",
    "#     print(anchors[:, 2])\n",
    "    anchors[:, 3] = anchors[:, 2] * np.repeat(ratios, len(scales) * len(rotations))\n",
    "#     print(anchors[:,3])\n",
    "    # add rotations\n",
    "    anchors[:, 4] = np.tile(np.repeat(rotations, len(scales)), (1, len(ratios))).T[:, 0]\n",
    "    # transform from (x_ctr, y_ctr, w, h) -> (x1, y1, x2, y2)\n",
    "    anchors[:, 0:3:2] -= np.tile(anchors[:, 2] * 0.5, (2, 1)).T\n",
    "    anchors[:, 1:4:2] -= np.tile(anchors[:, 3] * 0.5, (2, 1)).T\n",
    "    return anchors\n",
    "\n",
    "def shift(shape, stride, anchors):\n",
    "#     print(shape,\"\\n\",stride,\"\\n\",anchors)\n",
    "    shift_x = (np.arange(0, shape[1]) + 0.5) * stride\n",
    "    shift_y = (np.arange(0, shape[0]) + 0.5) * stride\n",
    "    shift_x, shift_y = np.meshgrid(shift_x, shift_y)\n",
    "    shifts = np.vstack((\n",
    "        shift_x.ravel(), shift_y.ravel(),\n",
    "        shift_x.ravel(), shift_y.ravel(),\n",
    "        np.zeros(shift_x.ravel().shape)\n",
    "    )).transpose()\n",
    "    # add A anchors (1, A, 4) to\n",
    "    # cell K shifts (K, 1, 4) to get\n",
    "    # shift anchors (K, A, 4)\n",
    "    # reshape to (K*A, 4) shifted anchors\n",
    "    A = anchors.shape[0]\n",
    "    K = shifts.shape[0]\n",
    "    all_anchors = (anchors.reshape((1, A, 5)) + shifts.reshape((1, K, 5)).transpose((1, 0, 2)))\n",
    "    all_anchors = all_anchors.reshape((K * A, 5))\n",
    "    return all_anchors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[-11.3137085 -22.627417   11.3137085  22.627417    0.       ]\n",
      " [-11.3137085 -22.627417   11.3137085  22.627417   90.       ]\n",
      " [-16.        -16.         16.         16.          0.       ]\n",
      " [-16.        -16.         16.         16.         90.       ]\n",
      " [-22.627417  -11.3137085  22.627417   11.3137085   0.       ]\n",
      " [-22.627417  -11.3137085  22.627417   11.3137085  90.       ]]\n",
      "[64 64]\n",
      "stride [8, 16, 32, 64, 128]\n",
      "image_shapes [array([64, 64]), array([32, 32]), array([16, 16]), array([8, 8]), array([4, 4])]\n",
      "24576\n"
     ]
    }
   ],
   "source": [
    "#使得print能够打印出全部信息\n",
    "\n",
    "np.set_printoptions(threshold=np.inf)\n",
    "base_size = [4]\n",
    "ratios = [2,1,0.5]#指定anchor的长宽比，保持面积不变的情况下，调整长宽比\n",
    "scales = [2]\n",
    "rotations = [0,90]#指定anchor的旋转角度\n",
    "ims_shape = np.array([512,512])\n",
    "pyramid_levels = [3, 4, 5, 6, 7]\n",
    "strides = []\n",
    "idx = 0 #pyramid_levels里的第几层\n",
    "\n",
    "sizes = [2 ** (x+1 ) for x in pyramid_levels]\n",
    "\n",
    "anchors = generate_anchors(sizes[idx], ratios, scales, rotations)\n",
    "\n",
    "\n",
    "sa = rbbx_overlaps(\n",
    "    xyxy2xywh_a(anchors[j, :, :].cpu().numpy()),\n",
    "    xyxy2xywh_a(bbox_annotation[:, :-1].cpu().numpy()),\n",
    ")\n",
    "print(anchors)\n",
    "\n",
    "\n",
    "# image_shapes = [(ims_shape + 2 ** x - 1) // (2 ** x) for x in pyramid_levels]\n",
    "# print(image_shapes[idx])\n",
    "# strides =[2 ** x for x in pyramid_levels]\n",
    "# print(\"stride\",strides)\n",
    "# print(\"image_shapes\",image_shapes)\n",
    "# shifted_anchors = shift(image_shapes[idx], strides[idx], anchors)\n",
    "# print(len(shifted_anchors))\n",
    "# print(shifted_anchors)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "GT的角度 tensor(8.7423e-08)\n",
      "anchor的角度 tensor(8.7423e-08)\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import numpy as np\n",
    "gt_thetas = torch.tensor(180)\n",
    "ex_thetas = torch.tensor(89)\n",
    "gt = torch.tan(gt_thetas / 180.0 * np.pi)\n",
    "#an = torch.tan(ex_thetas / 180.0 * np.pi)\n",
    "\n",
    "an = torch.tan(torch.tensor(3.141592653/2))\n",
    "\n",
    "print(\"GT的角度\",gt)\n",
    "print(\"anchor的角度\",an)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
